﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Dal;
using ADONetDal;
using Policlinica;
using NLog;

namespace OSA.Policlinic.BusinessApplication.Registry
{
    public class RegistryBusinessApplication : IRegistryBusinessApplication
    {          
        protected readonly IRepository<Patient> PatientRepository;
        public readonly IRepository<Address> AddressRepository;
        protected readonly IRepository<InsurancePolis> InsurancePolisRepository;
        protected readonly IRepository<InsuranceOrganization> InsuranceOrganizationRepository;
        protected readonly IRepository<Doctor> DoctorRepository;
        protected readonly IRepository<MedService> MedServiceRepository;
        protected readonly IRepository<KKF> KKFRepository;
        protected readonly IRepository<Ticket> TicketRepository;
        protected readonly IRepository<Vaccina> VaccinaRepository;
        private static Logger logger = LogManager.GetCurrentClassLogger();

        public RegistryBusinessApplication()
        {
            PatientRepository = new ADONetRepositoryPatient();
            AddressRepository = new ADONetRepositoryAddress();
            InsurancePolisRepository = new ADONetRepositoryInsurancePolis();
            InsuranceOrganizationRepository = new ADONetRepositoryInsuranceOrganisation();
            DoctorRepository = new ADONetRepositoryDoctor();
            MedServiceRepository = new ADONetRepositoryMedService();
            KKFRepository = new ADONetRepositoryKKF();
            TicketRepository = new ADONetRepositoryTicket();
            VaccinaRepository = new ADONetRepositoryVaccina();
        }

        public RegistryBusinessApplication(IRepository<Patient> patientRepository, IRepository<Address> addressRepository,
            IRepository<InsurancePolis> insurancePolisRepository, IRepository<InsuranceOrganization> insuranceOrganizationRepository,
            IRepository<Doctor> doctorRepository, IRepository<MedService> medServiceRepository,
            IRepository<KKF> kkfRepository, IRepository<Ticket> ticketRepository, IRepository<Vaccina> vaccinaRepository)
        {
            PatientRepository = patientRepository;
            AddressRepository = addressRepository;
            InsurancePolisRepository = insurancePolisRepository;
            InsuranceOrganizationRepository = insuranceOrganizationRepository;
            DoctorRepository = doctorRepository;
            MedServiceRepository = medServiceRepository;
            KKFRepository = kkfRepository;
            TicketRepository = ticketRepository;
            VaccinaRepository = vaccinaRepository;
        }

        public List<Patient> GetAllPatients()
        {
            try
            {
                return PatientRepository.GetList();
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public Patient GetPatientById(int id)
        {
            try
            {
                return PatientRepository.GetById(id);
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public Patient SavePatient(Patient patient)
        {
            try
            {
                patient.Address.Id = Save(patient.Address, AddressRepository).Id;
                patient.InsurancePolis.Id = Save(patient.InsurancePolis, InsurancePolisRepository).Id;
                return Save(patient, PatientRepository);
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public Patient UpdatePatient(Patient patient)
        {
            try
            {
                return Save(patient, PatientRepository);
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public Doctor GetDoctorById(int id)
        {
            try
            {
                return DoctorRepository.GetById(id);
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public List<Doctor> GetAllDoctors()
        {
            try
            {
                return DoctorRepository.GetList();
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public MedService GetMedServiceById(int id)
        {
            try
            {
                return MedServiceRepository.GetById(id);
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public List<MedService> GetAllMedServices()
        {
            try
            {
                return MedServiceRepository.GetList();
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public KKF SaveKKF(KKF kkf)
        {
            try
            {
                return Save(kkf, KKFRepository);
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public Ticket SaveTicket(Ticket ticket) 
        {
            try
            {
                return Save(ticket, TicketRepository);
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public InsurancePolis GetInsurancePolisById(int id)
        {
            try
            {
                return InsurancePolisRepository.GetById(id);
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public InsurancePolis SaveInsurancePolis(InsurancePolis polis)
        {
            try
            {
                return Save(polis, InsurancePolisRepository);
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public List<Patient> GetPatientByPolisNumber(string series, string polisNumber)
        {
            try
            {
                //список полисов с номером polisNumber
                List<InsurancePolis> polis = InsurancePolisRepository.GetByParameter(polisNumber, "PolisNumber");
                //удаление из списка полисов, серия которых != series
                for (int i = 0; i < polis.Count; i++)
                    if (polis[i].Series.ToLower() != series.ToLower())
                    {
                        polis.Remove(polis[i]);
                        i--;
                    }
                //получение нужного пациента
                if (polis.Count == 0)
                    return null;
                return PatientRepository.GetByParameter(polis[0].Id, "InsurancePolisId");
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public List<Doctor> GetDoctorsBySpecialisation(string specialisation)
        {
            try
            {
                return DoctorRepository.GetByParameter(specialisation, "Specialisation");
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public List<KKF> GetKKFByPatientId(int patientId)
        {
            try
            {
                return KKFRepository.GetByParameter(patientId, "PatientId");
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public InsuranceOrganization SaveInsuranceOrganisation(InsuranceOrganization org)
        {
            try
            {
                org.Address.Id = Save(org.Address, AddressRepository).Id;
                return Save(org, InsuranceOrganizationRepository);
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public List<InsuranceOrganization> GetAllInsuranceOrganizations()
        {
            try
            {
                return InsuranceOrganizationRepository.GetList();
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public List<Patient> GetPatientsBySurname(string surname)
        {
            try
            {
                return PatientRepository.GetByParameter(surname, "Surname");
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public List<Vaccina> GetVaccinaByPatientId(int patientId)
        {
            try
            {
                return VaccinaRepository.GetByParameter(patientId, "PatientId");
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public Vaccina SaveVaccina(Vaccina vaccina)
        {
            try
            {
                return Save(vaccina, VaccinaRepository);
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        public List<Ticket> GetTicketsByDoctor(Doctor doctor)
        {
            try
            {
                return TicketRepository.GetByParameter(doctor.Id, "DoctorId");
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

        private T Save<T>(T entity, IRepository<T> repository) where T : BusinessObjectBase
        {
            try
            {
                if (entity.IsNew)
                    return repository.Insert(entity);
                else
                    return repository.Update(entity);
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
                return null;
            }
        }

    }
}
